/// <reference path="typings/jquery/jquery.d.ts" />
/// <reference path="typings/bootstrap/bootstrap.d.ts" />
/// <reference path="typings/knockout/knockout.d.ts" />
/// <reference path="typings/signalr/signalr.d.ts" />
var AttachmentType;
(function (AttachmentType) {
    AttachmentType[AttachmentType["PICTURE"] = 0] = "PICTURE";
    AttachmentType[AttachmentType["VOICE"] = 1] = "VOICE";
    AttachmentType[AttachmentType["VIDEO"] = 2] = "VIDEO";
    AttachmentType[AttachmentType["UNKNOWN"] = 3] = "UNKNOWN";
})(AttachmentType || (AttachmentType = {}));
var AdminLevel;
(function (AdminLevel) {
    AdminLevel[AdminLevel["USER"] = 0] = "USER";
    AdminLevel[AdminLevel["VOICE"] = 1] = "VOICE";
    AdminLevel[AdminLevel["ADMIN"] = 2] = "ADMIN";
})(AdminLevel || (AdminLevel = {}));
var ChatViewModel = (function () {
    function ChatViewModel() {
        var _this = this;
        this.State = ko.observable(0);
        // Register/Login variables
        this.Nick = ko.observable("");
        this.Email = ko.observable("");
        this.Password = ko.observable("");
        this.Password2 = ko.observable("");
        this.Loading = ko.observable(false);
        // Chat variables
        this.Channels = ko.observableArray([]);
        this.CurrentChannel = ko.observable("");
        this.CurrentUserList = ko.observableArray([]);
        this.Message = ko.observable("");
        this.CurrentMessages = ko.observableArray([]);
        this.Attachments = {};
        // The ID of the selected user or null if no user selected
        this.SelectedUser = ko.observable("");
        this.SignalrChat = null;
        // Join template
        this.JoinInput = ko.observable("").extend({ rateLimit: 500 });
        this.JoinQueryResults = ko.observableArray([]);
        this.JoinChannel = function (data, event) {
            $.ajax("/api/Chat/" + encodeURIComponent(data), _this.getAjaxLoggedInOpts("PUT")).done(function (rdata) {
                if (_this.Channels().length == 0) {
                    // This is our first joined channel
                    _this.Channels.push(rdata);
                    _this.InitChat(rdata);
                }
                else {
                    rdata.Messages = [];
                    rdata.UserList = [];
                    _this.Channels.push(rdata);
                    _this.ChatState();
                    _this.ChangeChannel(rdata);
                }
            }).fail(function (error) {
                console.error(error);
                alert(error.responseJSON.Message);
            });
        };
        this.ChangeChannel = function (data, event) {
            if (event === void 0) { event = null; }
            _this.CurrentChannel(data.HashTag);
            _this.SelectedUser("");
            if (data.UserList.length > 0) {
                _this.CurrentUserList(data.UserList);
                _this.CurrentMessages(data.Messages);
                _this.scrollToBottom();
                return;
            }
            _this.GetChannelUsers(data.HashTag);
            _this.GetChannelMessages(data.HashTag);
        };
        this.SetUser = function (selectedUser, event) {
            if (_this.SelectedUser() == selectedUser.Id) {
                _this.SelectedUser("");
                return;
            }
            _this.SelectedUser(selectedUser.Id);
        };
        this.JoinInput.subscribe(function (newValue) {
            $.ajax("/api/Channel/" + encodeURIComponent(newValue), _this.getAjaxLoggedInOpts("GET")).done(function (Channels) {
                var schannels = [];
                for (var i = 0; i < Channels.length; i++) {
                    schannels.push(Channels[i].HashTag);
                }
                _this.JoinQueryResults(schannels);
            });
        }, this);
        var token = this.getBearerToken();
        if (token) {
            this.InitChannels();
        }
    }
    ChatViewModel.prototype.JoinHeseNyymit = function () {
        this.JoinChannel("#hesenyymit", null);
    };
    ChatViewModel.prototype.LeaveChannel = function () {
        var _this = this;
        if (!confirm("Leave channel " + this.CurrentChannel() + "?"))
            return;
        $.ajax("/api/Chat/" + encodeURIComponent(this.CurrentChannel()), this.getAjaxLoggedInOpts("DELETE")).done(function (rdata) {
            if (_this.Channels().length == 1) {
                // This is our last joined channel
                _this.DisconnectFromChat();
                _this.State(2);
            }
            else {
                _this.Channels.remove(function (item) {
                    return item.HashTag == _this.CurrentChannel();
                });
                _this.ChangeChannel(_this.Channels()[0]);
            }
        }).fail(function (error) {
            console.error(error);
            alert(error.responseJSON.Message);
        });
    };
    ChatViewModel.prototype.CreateChannel = function () {
        var _this = this;
        var data = {
            HashTag: "#" + this.JoinInput(),
            Topic: "Change me!",
            Private: false
        };
        $.ajax("/api/Channel", this.getAjaxLoggedInOpts("POST", data)).done(function (rdata) {
            data.Messages = [];
            data.UserList = [];
            if (_this.Channels().length == 0) {
                _this.Channels.push(data);
                _this.InitChat(data);
            }
            else {
                _this.Channels.push(data);
                _this.CurrentChannel(data.HashTag);
                var luser = {
                    Id: "1",
                    Nick: _this.Nick(),
                    AdminState: 2 /* ADMIN */
                };
                _this.CurrentUserList([]);
                _this.CurrentUserList.push(luser);
                _this.CurrentMessages([]);
                _this.State(3);
            }
        }).fail(function (error) {
            console.error(error);
            alert(error.responseJSON.Message);
        });
    };
    // Simple validation and the ajax call to register.
    ChatViewModel.prototype.Register = function () {
        var _this = this;
        if (this.Nick().length < 1)
            return;
        if (this.Email().length < 1)
            return;
        if (this.Password().length < 1 || this.Password2().length < 1)
            return;
        if (this.Password() != this.Password2())
            return;
        var data = {
            Email: this.Email(),
            Nick: this.Nick(),
            Password: this.Password(),
            ConfirmPassword: this.Password2()
        };
        $.ajax("/api/Account/Register", this.getAjaxLoggedOutOpts("POST", data)).done(function (rdata) {
            console.log(rdata);
            _this.Login();
        }).fail(function (error) {
            console.error(error);
            alert(error.responseJSON.error_description);
        });
    };
    ChatViewModel.prototype.Login = function () {
        var _this = this;
        if (this.Nick().length < 1)
            return;
        if (this.Password().length < 1)
            return;
        if (this.Loading() == true)
            return;
        this.Loading(true);
        var data = "grant_type=password&username=" + this.Nick() + "&password=" + this.Password();
        var opts = {
            method: "POST",
            data: data,
            cache: false,
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
        };
        $.ajax("/Token", opts).done(function (rdata) {
            console.log(rdata);
            _this.setBearerToken(rdata.access_token); //, userName: loginData.userName }
            _this.InitChannels();
        }).fail(function (error) {
            console.error(error);
            alert(error.responseJSON.error_description);
            _this.Loading(false);
        });
    };
    // Gets the user's channels and starts the chat
    ChatViewModel.prototype.InitChannels = function () {
        var _this = this;
        this.GetChannels().done(function (Channels) {
            if (Channels.length > 0) {
                for (var i = 0; i < Channels.length; i++) {
                    Channels[i].UserList = [];
                    Channels[i].Messages = [];
                }
                _this.Channels(Channels);
                _this.InitChat(Channels[0]);
            }
            else {
                _this.State(2);
            }
        }).fail(function (error) {
            _this.setBearerToken(null);
        }).always(function () {
            _this.Loading(false);
        });
    };
    // Initialize the chat with channel
    ChatViewModel.prototype.InitChat = function (channel) {
        var _this = this;
        this.CurrentChannel(channel.HashTag);
        var pr1 = this.GetChannelUsers(channel.HashTag);
        var pr2 = this.GetChannelMessages(channel.HashTag);
        $.when(pr1, pr2).done(function (result1, result2) {
            _this.State(3);
            _this.scrollToBottom();
            _this.ConnectToChat();
        }).fail(function (error) {
            console.error(error);
        });
    };
    // Initializes the SignalR protocol for chat
    ChatViewModel.prototype.ConnectToChat = function () {
        var _this = this;
        this.SignalrChat = $.connection.chatHub;
        // This is ran every time message is received
        this.SignalrChat.client.receive = function (data) {
            data.TimeStamp = new Date(data.TimeStamp.toString());
            if (data.AttachmentId) {
                var attachment = {
                    Id: data.AttachmentId,
                    URL: ko.observable("")
                };
                _this.Attachments[data.AttachmentId] = attachment;
                _this.GetAttachment(data.AttachmentId);
            }
            if (_this.CurrentChannel() == data.HashTag) {
                _this.CurrentMessages.push(data);
            }
            else {
                for (var i = 0; i < _this.Channels().length; i++) {
                    if (data.HashTag != _this.Channels()[i].HashTag)
                        continue;
                    _this.Channels()[i].Messages.push(data);
                    break;
                }
            }
            if (data.SystemMessage == true) {
                _this.GetChannelUsers(data.HashTag);
            }
            _this.scrollToBottom();
        };
        this.createCookie("Bearer", this.getBearerToken(), 1);
        $.connection.hub.start().done(function () {
            console.log("Signalr started");
        });
    };
    ChatViewModel.prototype.DisconnectFromChat = function () {
        $.connection.hub.stop();
    };
    ChatViewModel.prototype.GetAttachment = function (attachmentId, scroll) {
        var _this = this;
        if (scroll === void 0) { scroll = false; }
        return $.ajax("/api/Attachment/" + encodeURIComponent(attachmentId), this.getAjaxLoggedInOpts("GET")).done(function (rdata) {
            _this.Attachments[attachmentId].InternalName = rdata.InternalName;
            _this.Attachments[attachmentId].OriginalName = rdata.OriginalName;
            _this.Attachments[attachmentId].Type = rdata.Type;
            _this.Attachments[attachmentId].URL(rdata.InternalName);
            if (scroll)
                _this.scrollToBottom();
        });
    };
    ChatViewModel.prototype.SendAttachment = function () {
        var _this = this;
        var file = $("#attachment").prop("files")[0];
        if (file == void 0)
            return false;
        var formData = new FormData();
        formData.append("file-0", file);
        jQuery.ajax({
            url: "/api/Attachment/",
            data: formData,
            cache: false,
            contentType: false,
            processData: false,
            type: "POST",
            headers: {
                'Authorization': 'Bearer ' + this.getBearerToken()
            }
        }).done(function (rdata) {
            $("#InlineChatForm")[0].reset();
            if (rdata.length == 0) {
                console.log("Attachment was ignored!");
                _this.SendMessageEx();
                return;
            }
            console.log("AttachmentId: " + rdata[0]);
            _this.SendMessageEx(rdata[0]);
        }).fail(function (error) {
            console.error("Failed to send the attachment!");
        });
        return true;
    };
    ChatViewModel.prototype.SendMessageEx = function (attachmentId) {
        var _this = this;
        if (attachmentId === void 0) { attachmentId = null; }
        var data = {
            HashTag: this.CurrentChannel(),
            Message: this.Message(),
            AttachmentId: attachmentId
        };
        $.ajax("/api/Chat/", this.getAjaxLoggedInOpts("POST", data)).done(function (rdata) {
            _this.Message("");
        });
    };
    ChatViewModel.prototype.SendMessage = function () {
        if (this.SendAttachment())
            return;
        this.SendMessageEx();
    };
    ChatViewModel.prototype.CheckForEnter = function (data, event) {
        if (event.keyCode == 13) {
            this.SendMessage();
        }
        return true;
    };
    ChatViewModel.prototype.GetChannels = function () {
        return $.ajax("/api/UserList/MyChannels", this.getAjaxLoggedInOpts());
    };
    ChatViewModel.prototype.GetChannelUsers = function (channelName) {
        var _this = this;
        return $.ajax("/api/UserList/Users/" + encodeURIComponent(channelName), this.getAjaxLoggedInOpts("GET")).done(function (users) {
            for (var i = 0; i < _this.Channels().length; i++) {
                if (_this.Channels()[i].HashTag == channelName) {
                    _this.Channels()[i].UserList = users;
                    break;
                }
            }
            if (_this.CurrentChannel() == channelName) {
                _this.CurrentUserList(users);
            }
        });
    };
    ChatViewModel.prototype.GetChannelMessages = function (channelName) {
        var _this = this;
        return $.ajax("/api/Chat/" + encodeURIComponent(channelName), this.getAjaxLoggedInOpts()).done(function (messages) {
            for (var i = 0; i < messages.length; i++) {
                messages[i].TimeStamp = new Date(messages[i].TimeStamp.toString());
                if (messages[i].AttachmentId) {
                    var attachment = {
                        Id: messages[i].AttachmentId,
                        URL: ko.observable("")
                    };
                    _this.Attachments[messages[i].AttachmentId] = attachment;
                    _this.GetAttachment(messages[i].AttachmentId, true);
                }
            }
            for (var i = 0; i < _this.Channels().length; i++) {
                if (_this.Channels()[i].HashTag == channelName) {
                    _this.Channels()[i].Messages = messages;
                    break;
                }
            }
            if (_this.CurrentChannel() == channelName) {
                _this.CurrentMessages(messages);
            }
        });
    };
    ChatViewModel.prototype.GetNick = function (userId) {
        for (var i = 0; i < this.CurrentUserList().length; i++) {
            if (this.CurrentUserList()[i].Id == userId)
                return this.CurrentUserList()[i].Nick;
        }
        return "?";
    };
    ChatViewModel.prototype.GetTimeString = function (time) {
        return time.toUTCString();
    };
    ChatViewModel.prototype.RegisterState = function () {
        this.State(1);
        return true;
    };
    ChatViewModel.prototype.LoginState = function () {
        this.State(0);
        return true;
    };
    ChatViewModel.prototype.JoinChannelState = function () {
        this.State(4);
        return true;
    };
    ChatViewModel.prototype.ChatState = function () {
        this.State(3);
        return true;
    };
    ChatViewModel.prototype.getAjaxLoggedOutOpts = function (method, data) {
        if (method === void 0) { method = "GET"; }
        if (data === void 0) { data = null; }
        if (data)
            data = JSON.stringify(data);
        var opts = {
            method: method,
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: data,
            cache: false
        };
        return opts;
    };
    ChatViewModel.prototype.getAjaxLoggedInOpts = function (method, data, json) {
        if (method === void 0) { method = "GET"; }
        if (data === void 0) { data = null; }
        if (json === void 0) { json = true; }
        if (data && json)
            data = JSON.stringify(data);
        var opts = {
            method: method,
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: data,
            cache: false,
            headers: {
                'Authorization': 'Bearer ' + this.getBearerToken()
            }
        };
        return opts;
    };
    ChatViewModel.prototype.getBearerToken = function () {
        return sessionStorage.getItem("bearertoken");
    };
    ChatViewModel.prototype.setBearerToken = function (token) {
        sessionStorage.setItem("bearertoken", token);
    };
    ChatViewModel.prototype.createCookie = function (name, value, days) {
        if (days) {
            var date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            var expires = "; expires=" + date.toUTCString();
        }
        else
            var expires = "";
        document.cookie = name + "=" + value + expires + "; path=/";
    };
    ChatViewModel.prototype.scrollToBottom = function () {
        $("div.chatwell").scrollTop($("div.chatwell")[0].scrollHeight);
    };
    ChatViewModel.prototype.getMessageTemplate = function (msg) {
        return msg.SystemMessage ? "system-message-template" : "normal-message-template";
    };
    ChatViewModel.prototype.getSystemMessage = function (text) {
        if (text && text[0] == "@")
            return text.substring(text.indexOf(" "));
        return text;
    };
    return ChatViewModel;
})();
ko.applyBindings(new ChatViewModel());
//# sourceMappingURL=ChatViewModel.js.map